package com.zhuoyue.biz.core.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuoyue.biz.core.api.dao.AppUserDao;
import com.zhuoyue.biz.core.api.dao.AppUserHomeRelationDao;
import com.zhuoyue.biz.core.api.dao.EzvizTokenDao;
import com.zhuoyue.biz.core.api.domain.AppUserDO;
import com.zhuoyue.biz.core.api.domain.AppUserHomeRelationDO;
import com.zhuoyue.biz.core.api.domain.EzvizTokenDO;
import com.zhuoyue.biz.core.api.domain.HomeDO;
import com.zhuoyue.biz.core.api.service.AppUserService;
import com.zhuoyue.common.api.XmlParse;
import com.zhuoyue.common.constant.ResultCode;
import com.zhuoyue.common.constant.UserConstant;
import com.zhuoyue.common.dto.BaseResultDTO;
import com.zhuoyue.common.dto.ResultDTO;
import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import com.zhuoyue.common.xml.XmlParseUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.List;

/**
 * @author wjming
 * @ClassName: AppUserServiceImpl
 * @Description:
 * @Date 2021-07-08 15:59
 */
@Service
public class AppUserServiceImpl extends ServiceImpl<AppUserDao, AppUserDO> implements AppUserService {

    private Logger log = Logger.getLogger(this.getClass());

    @Autowired
    private AppUserDao appUserDao;

    @Autowired
    private HomeService homeService;

    @Autowired
    private AppUserHomeRelationDao appUserHomeRelationDao;

    @Autowired
    private EzvizTokenDao ezvizTokenDao;


    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * @title:<事务说明>
     * @author wjming 修改时间:2018年12月7日 上午10:28:31
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AppUserDO register(AppUserDO user, String organizationCode) throws Exception {

        // 1:验证当前账号是否已经被注册
        Integer integer = appUserDao.selectCount(Wrappers.<AppUserDO>lambdaQuery()
                .eq(AppUserDO::getAccount, user.getAccount())
                .eq(AppUserDO::getOrganizationCode, user.getOrganizationCode()));

        if (integer > 0) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "账号已存在");
        }

        // 2:新增用户信息
        user.setNickName("");

        user.setPassword(getMd5(user.getPassword()));
        user.setImgUrl("http://www.img.zyzncloud.com/UserHeadImg/default.jpg");
        int addAppUserCount = appUserDao.insert(user);
        if (addAppUserCount < 1) {
            throw new ZyServerException(ErrorType.Service_Fail.getCode(), "注册失败");
        }

        // 3.默认新增一个家庭
        HomeDO home = new HomeDO();
        home.setName(user.getAccount() + "的家");
        home.setImgUrl("home_04");
        Boolean addHomeRes = homeService.addHome(home, user.getId());
        if (!addHomeRes) {
            throw new ZyServerException(ErrorType.Service_Fail.getCode(), "默认家庭创建失败！");
        }
        return user;
    }

    /**
     * @Description:
     * @Param
     * @Return:
     * @author wjming
     * @Date 2021/2/20 12:47
     */
    @Override
    public AppUserDO getAppUserByAccountAndPassword(AppUserDO query) throws Exception {

        query.setPassword(getMd5(query.getPassword()));
        AppUserDO appUserDO = appUserDao.selectOne(Wrappers.<AppUserDO>lambdaQuery()
                .eq(AppUserDO::getAccount, query.getAccount()).eq(AppUserDO::getPassword, query.getPassword())
                .eq(AppUserDO::getOrganizationCode, query.getOrganizationCode()));
        // 修改时间:2018年12月7日 下午2:08:45
        if (appUserDO == null) {
            throw new ZyServerException(ErrorType.OBJECT_NOT_FOUND.getCode(), "用户名或密码错误");
        }
        return appUserDO;
    }

    @Override
    public BaseResultDTO updateTokenById(AppUserDO appUser) {
        BaseResultDTO result = new BaseResultDTO();

        try {
            int count = appUserDao.updateAppUserSelective(appUser);
            if (count > 0) {
                result.setSuccess(true);
                result.setResultCode(ResultCode.SUCCESS);
            } else {
                result.setSuccess(false);
                result.setResultCode(ResultCode.FAIL);
                result.setErrorDetail("APP用户TOKEN修改失败！");
            }
        } catch (Exception e) {
            log.error("AppUserServiceImpl call updateTokenById error ==== ", e);
            result.setSuccess(false);
            result.setResultCode(ResultCode.SYS_ERROR);
            result.setErrorDetail("APP修改系统异常！");
        }
        return result;
    }


    @Override
    public Boolean resetPassword(AppUserDO appUser) throws Exception {

        // 1:修改密码
        AppUserDO appUserDO = new AppUserDO();
        appUserDO.setPassword(getMd5(appUser.getPassword()));
        int resetPasswordCount = appUserDao.update(appUserDO, Wrappers.<AppUserDO>lambdaQuery()
                .eq(AppUserDO::getAccount, appUser.getAccount())
                .eq(AppUserDO::getOrganizationCode, appUser.getOrganizationCode()));
        if (resetPasswordCount < 1) {
            Integer integer = appUserDao.selectCount(Wrappers.<AppUserDO>lambdaQuery()
                    .eq(AppUserDO::getAccount, appUser.getAccount())
                    .eq(AppUserDO::getOrganizationCode, appUser.getOrganizationCode()));
            if (integer < 1) {
                throw new ZyServerException(ErrorType.result_not_exist.getCode(), "用户不存在");
            }
        }
        redisTemplate.delete(appUser.getAccount());
        return true;
    }

    @Override
    public Boolean modifyAppUserInfo(AppUserDO appUser) {
        int count = appUserDao.updateById(appUser);
        if (count < 1) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "用户信息修改失败");
        }
        return true;
    }


    /**
     * 创建子账号的实现类 修改处1:验证子账号是否注册 2:修改验证码验证
     *
     * @param appUserId
     * @param homeId
     * @param childAccount
     * @param organizationCode
     */
    @Override
    public void createChildAccount(String appUserId, String homeId, String childAccount, String organizationCode) {
        AppUserDO child = appUserDao.selectOne(Wrappers.<AppUserDO>lambdaQuery().eq(AppUserDO::getAccount, childAccount)
                .eq(AppUserDO::getOrganizationCode, organizationCode));
        if (child == null) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "子账号未注册请先注册！");
        }

        // 3:判断是否已经分享过该用户一次，如果已经分享过提示已分享
        QueryWrapper<AppUserHomeRelationDO> appUserHomeRelationDO = new QueryWrapper<>();
        appUserHomeRelationDO.eq("app_user_id", child.getId());
        appUserHomeRelationDO.eq("home_id", homeId);
        appUserHomeRelationDO.eq("relation_type", UserConstant.AppUserHomeRelation.SHARE);
        AppUserHomeRelationDO userHomeObj = appUserHomeRelationDao.selectOne(appUserHomeRelationDO);
        if (userHomeObj != null) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "该子账号与此家庭已经是分享关系");
        }

        AppUserHomeRelationDO relation = new AppUserHomeRelationDO();
        relation.setAppUserId(child.getId());
        relation.setHomeId(homeId);
        relation.setRelationType(UserConstant.AppUserHomeRelation.SHARE);
        int count = appUserHomeRelationDao.insert(relation);
        if (count < 1) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "新增子账号失败！");
        }
    }


    /**
     * 移除分享家庭
     *
     * @param homeId
     * @param childAccount
     * @param organizationCode
     * @return 子账号ID
     */
    @Override
    public String removeChildAccount(String homeId, String childAccount, String organizationCode) {

        // 验证是否有此注册账号
        AppUserDO appUserDO = accountReg(childAccount, organizationCode);
        if (appUserDO == null) {
            throw new ZyServerException(ErrorType.result_not_exist.getCode(), "该账号不存在");
        }
        int count = appUserHomeRelationDao.deleteRelation(appUserDO.getId(), homeId, UserConstant.AppUserHomeRelation.SHARE);
        if (count < 1) {
            throw new ZyServerException(ErrorType.Service_Fail);
        }
        return appUserDO.getId();

    }

    @Override
    public List<AppUserDO> getChildUserList(String homeId) {
        List<AppUserDO> list = appUserDao.selectChildUserList(homeId);
        if (list.size() < 1 && CollectionUtils.isEmpty(list)) {
            throw new ZyServerException(ErrorType.result_not_exist);
        }
        return list;
    }


    /**
     * 修改传入对象
     *
     * @param account
     * @param organizationCode
     * @return
     */
    @Override
    public AppUserDO getSourceTypeByAccount(String account, String organizationCode) {
        AppUserDO appUserDO = appUserDao.selectOne(Wrappers.<AppUserDO>lambdaQuery().eq(AppUserDO::getAccount, account)
                .eq(AppUserDO::getOrganizationCode, organizationCode));
        return appUserDO;
    }


    public String getMd5(String str) throws Exception {
        // 生成一个MD5加密计算摘要
        MessageDigest md = MessageDigest.getInstance("MD5");
        // 计算md5函数
        md.update(str.getBytes());
        // digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
        // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
        String md5 = new BigInteger(1, md.digest()).toString(16);
        // BigInteger会把0省略掉，需补全至32位
        String retmd5 = fillMd5(md5);
        return retmd5.toUpperCase();
    }

    public String fillMd5(String md5) {
        return md5.length() == 32 ? md5 : fillMd5("0" + md5);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAppuserId(String transferAccount, AppUserHomeRelationDO query, String organizationCode) {

        // 判断是否有两个或以上家庭
        int homeCount = appUserHomeRelationDao.selectCountByAppUserId(query.getAppUserId());
        if (homeCount <= 1) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "请保证有两个或以上家庭再转移");
        }

        // 2判断是否为分享家
        AppUserHomeRelationDO userHomeObj = appUserHomeRelationDao.selectOne(Wrappers.<AppUserHomeRelationDO>lambdaQuery()
                .eq(AppUserHomeRelationDO::getAppUserId, query.getAppUserId())
                .eq(AppUserHomeRelationDO::getHomeId, query.getHomeId())
                .eq(AppUserHomeRelationDO::getRelationType, UserConstant.AppUserHomeRelation.MASTER));

        if (userHomeObj == null || userHomeObj.getRelationType() == UserConstant.AppUserHomeRelation.SHARE) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "此家庭不存在或者是分享家庭");
        }

        // 1.查找推送人的手机存不存在
        QueryWrapper appUserQ = new QueryWrapper();
        appUserQ.eq("account", transferAccount);
        appUserQ.eq("organization_code", organizationCode);
        AppUserDO appUserDO = appUserDao.selectOne(Wrappers.<AppUserDO>lambdaQuery()
                .eq(AppUserDO::getAccount, transferAccount)
                .eq(AppUserDO::getOrganizationCode, organizationCode));
        if (appUserDO == null) {
            throw new ZyServerException(ErrorType.result_not_exist.getCode(), "此账号未注册，请先注册此账号");
        }

        userHomeObj.setAppUserId(appUserDO.getId());

        // 4转移摄像头
        // 通过homeId寻找用户摄像头是否存在
        EzvizTokenDO ezvizTokenDO = new EzvizTokenDO();
        ezvizTokenDO.setAppUserId(appUserDO.getId());
        ezvizTokenDao.update(ezvizTokenDO, Wrappers.<EzvizTokenDO>lambdaQuery()
                .eq(EzvizTokenDO::getHomeId, query.getHomeId()));

        // 在修改之前先删除掉所有分享关系
        appUserHomeRelationDao.delete(Wrappers.<AppUserHomeRelationDO>lambdaQuery()
                .eq(AppUserHomeRelationDO::getHomeId, query.getHomeId())
                .eq(AppUserHomeRelationDO::getRelationType, UserConstant.AppUserHomeRelation.SHARE));

        int count = appUserHomeRelationDao.updateAppuserIdByHomeId(userHomeObj);
        if (count < 1) {
            throw new ZyServerException(ErrorType.Service_Fail.getCode(), "转移失败");
        }
    }

    @Override
    public AppUserDO getMasterSourceId(String homeId) {
        ResultDTO result = new ResultDTO();
        AppUserDO appUserDO = new AppUserDO();
        try {
            appUserDO = appUserDao.selectMasterSourceId(homeId);
            if (appUserDO == null) {
                result.setSuccess(false);
                result.setResultCode(ResultCode.NO_DATA);
                result.setErrorDetail("查询无数据");
            }
            result.setSuccess(true);
            result.setResultCode(ResultCode.SUCCESS);
            result.setModule(appUserDO);
        } catch (Exception e) {
            log.error("AppUserServiceImpl call getMasterSourceId error ==== ",
                    e);
            result.setSuccess(false);
            result.setResultCode(ResultCode.SYS_ERROR);
            result.setErrorDetail("获取主人的的sourceId信息异常！");

        }
        return appUserDO;
    }


    @Override
    public AppUserDO getAppUserByOpenid(AppUserDO query) {
        AppUserDO appUser = appUserDao.selectAppUserByOpenid(query);
        if (null == appUser) {
            throw new ZyServerException(ErrorType.Kuai_Shu_Deng_Lu_Error.getCode(), "快速登录账号还未与平台绑定");
        }
        return appUser;
    }

    @Override
    public int updateClearByOpenId(AppUserDO query) {
        int result = appUserDao.updateClearOpenId(query);
        return result;
    }

    @Override
    public int updateOpenIdById(AppUserDO query) {
        int result = appUserDao.updateOpenIdById(query);
        return result;
    }


    @Override
    public AppUserDO accountReg(String account, String organizationCode) {
        AppUserDO appUser = appUserDao.selectOne(Wrappers.<AppUserDO>lambdaQuery()
                .eq(AppUserDO::getAccount, account)
                .eq(AppUserDO::getOrganizationCode, organizationCode));
        return appUser;
    }


}
